<script lang="ts" setup>
import { reactive, ref, shallowRef, onMounted, onActivated } from 'vue'
import { useMap } from '@/hooks/useMap'
import { useActivated } from '@/hooks/useActivated'
import { useRoute } from 'vue-router'
import SearchPlace from '@/components/map/SearchPlace.vue'
import bikeImg from '@/assets/map/timeBikeOperation/bike.png'
import bikeIconImg from '@/assets/map/timeBikeOperation/i_bike.png'
import phoneIconImg from '@/assets/map/timeBikeOperation/i_phone.png'
import phoneImg from '@/assets/map/timeBikeOperation/phone.png'
import MeasureTools from '@/components/map/MeasureTools.vue'
import { getToken } from '@/utils/cache/cookies'
import { queryShortTermRange } from '@/api/bike'
import { coordinatesType } from '@/api/bike/types/bike'
import { returnLocationType } from '@/types/interface'
import returnPointImg from '@/assets/map/bikeLocation/returnPoint.png'
import activeReturnPointImg from '@/assets/map/bikeLocation/activeReturnPoint.png'
import { ElMessage } from 'element-plus'
defineOptions({
  name: 'TimeBikeOperationLocation'
})
const route = useRoute()
const watchParams = reactive({
  deviceLongitude: Number(route.query.deviceLongitude),
  deviceLatitude: Number(route.query.deviceLatitude),
  userLatitude: Number(route.query.userLatitude),
  userLongitude: Number(route.query.userLongitude),
  createdTime: route.query.createdTime as string,
  bikeCode: route.query.bikeCode as string
})
const isInit = ref<boolean>(false)
const bikeAddress = ref<any>('')
const userAddress = ref<any>('')
const distance = ref<number>(0)
const mapContainer = ref<HTMLDivElement>()
const bikeMarker = shallowRef<AMap.Marker>()
const userMarker = shallowRef<AMap.Marker>()
const { map, auto, initAmap, placeSearch, getAddress, ruler, geocoder } = useMap(mapContainer, [
  watchParams?.deviceLongitude ?? 0,
  watchParams?.deviceLatitude ?? 0
])
/** 地图初始化 */
const init = async () => {
  isInit.value = await initAmap()
  await getRange()
  handleCoverInit()
}
/** 用于activated */
const handleActivated = async () => {
  handleCoverInit()
}
/** 获取车辆附近还车点 */
/** 转换数据用于初始化运营区域 */
const handleCoordinates = (data: coordinatesType[]) => {
  return data.map(
    (location: coordinatesType) => new AMap.LngLat(location.longtitude, location.latitude)
  )
}
/** 转换数据用于初始化海量点 */
const handleReturnLocation = (data: returnLocationType[]) => {
  return data.map((location: returnLocationType) => {
    return {
      lnglat: [location.longtitude, location.latitude] as [number, number],
      ...location
    }
  })
}
interface returnLocationMapType extends returnLocationType {
  lnglat: [number, number]
}
const coordinates = ref<AMap.LngLat[]>([])
const returnLocation = ref<returnLocationMapType[]>([])
const massmarks = ref<AMap.MassMarks>()
const infoWindow = shallowRef<AMap.InfoWindow>()
const circle = ref<AMap.Circle>()
const getRange = async () => {
  try {
    const res = await queryShortTermRange({
      token: getToken() ?? '',
      bikeCode: watchParams.bikeCode
    })
    coordinates.value = handleCoordinates(res.data.coordinates)
    returnLocation.value = handleReturnLocation(res.data.returnLocation)
  } catch (error) {
    console.error(error)
  }
}
/** 生成地图覆盖物 */
const handleCoverInit = async () => {
  if (isInit.value && map.value) {
    map.value.clearMap()
    bikeAddress.value = await getAddress(
      watchParams?.deviceLongitude ?? 0,
      watchParams?.deviceLatitude ?? 0
    )
    bikeMarker.value = new AMap.Marker({
      position: new AMap.LngLat(
        watchParams?.deviceLongitude ?? 0,
        watchParams?.deviceLatitude ?? 0
      ),
      map: map.value,
      icon: new AMap.Icon({
        image: bikeImg,
        imageSize: new AMap.Size(36, 36),
        size: new AMap.Size(36, 36)
      }),
      offset: new AMap.Pixel(-15, -36)
    })
    if (coordinates.value.length > 0) {
      const polygon = new AMap.Polygon({
        path: coordinates.value,
        strokeColor: '#418DFF',
        strokeOpacity: 1,
        strokeWeight: 3,
        fillColor: '#418DFF',
        fillOpacity: 0.1,
        strokeStyle: 'dashed',
        bubble: true
      })
      map.value?.add(polygon)
    }
    massmarks.value = new AMap.MassMarks(returnLocation.value, {
      style: getStyle(),
      zIndex: 110
    })
    massmarks.value.setMap(map.value)
    massmarks.value.on('click', handleMassMarksClick)
    if (watchParams.userLatitude && watchParams.userLongitude) {
      userAddress.value = await getAddress(
        watchParams?.userLongitude ?? 0,
        watchParams?.userLatitude ?? 0
      )
      userMarker.value = new AMap.Marker({
        position: new AMap.LngLat(watchParams?.userLongitude ?? 0, watchParams?.userLatitude ?? 0),
        map: map.value,
        icon: new AMap.Icon({
          image: phoneImg,
          imageSize: new AMap.Size(36, 36),
          size: new AMap.Size(36, 36)
        }),
        offset: new AMap.Pixel(-15, -36)
      })
      distance.value = AMap.GeometryUtil.distance(
        new AMap.LngLat(watchParams?.deviceLongitude ?? 0, watchParams?.deviceLatitude ?? 0),
        new AMap.LngLat(watchParams?.userLongitude ?? 0, watchParams?.userLatitude ?? 0)
      )
      map.value?.setFitView([bikeMarker.value, userMarker.value])
    } else map.value?.setFitView([bikeMarker.value])
  }
}
/** 海量点图层样式 */
const getStyle = () => {
  return [
    {
      anchor: new AMap.Pixel(0, 0),
      url: returnPointImg,
      size: new AMap.Size(30, 30)
    },
    {
      anchor: new AMap.Pixel(0, 0),
      url: activeReturnPointImg,
      size: new AMap.Size(30, 30)
    }
  ]
}
/** 点击海量点的事件 */
const handleMassMarksClick = (e: any) => {
  const index = returnLocation.value.findIndex(
    (item) => item.lnglat[1] === e.data.latitude && item.lnglat[0] === e.data.longtitude
  )
  circle.value?.setCenter(e.data.lnglat)
  circle.value?.setRadius(e.data.radius)
  if (infoWindow.value?.getIsOpen()) {
    infoWindow.value.close()
    returnLocation.value = returnLocation.value.map((item) => {
      return {
        ...item,
        style: 0
      }
    })
    massmarks.value?.setData(returnLocation.value)
    circle.value?.hide()
  } else {
    returnLocation.value = returnLocation.value.map((item, i) => {
      if (index == i) {
        return {
          ...item,
          style: 1
        }
      } else {
        return {
          ...item,
          style: 0
        }
      }
    })
    massmarks.value?.setData(returnLocation.value)
    geocoder.value.getAddress(e.data.lnglat, (status: any, result: any) => {
      if (result.info == 'OK') {
        const name = result.regeocode.aois
          ? result.regeocode.aois[0].name
          : result.regeocode.formattedAddress
        infoWindow.value?.setContent(
          createReturnLocationContent(e.data.address, e.data.returnLocationsId, name)
        )
      } else {
        // 处理获取地址失败的情况
        ElMessage.error('地址解析失败')
        infoWindow.value?.setContent(
          createReturnLocationContent(e.data.address, e.data.returnLocationsId, '')
        )
      }
      infoWindow.value?.open(map.value!, e.data.lnglat)
      circle.value?.show()
      map.value?.setCenter(e.data.lnglat)
    })
  }
  map.value?.setFitView([circle.value!!])
}
/** 海量点信息窗体内容 */
const createReturnLocationContent = (address: string, returnLocationsId: number, title: string) => {
  return `<div class="return-point-infowindow">
                  <div class="return-point-infowindow__title">
                    <span class="return-point-infowindow__name">${title}</span>
                    <div class="return-point-infowindow__id-content">
                        <span>编号:${returnLocationsId}</span>
                    </div>
                  </div>
                  <div class="return-point-infowindow__address">
                    <span>${address}</span>
                  </div>
              </div>`
}
onMounted(() => {
  init()
})
onActivated(() => {
  watchParams.deviceLongitude = Number(route.query.deviceLongitude)
  watchParams.deviceLatitude = Number(route.query.deviceLatitude)
  watchParams.userLatitude = Number(route.query.userLatitude)
  watchParams.userLongitude = Number(route.query.userLongitude)
  watchParams.bikeCode = route.query.bikeCode as string
})
/** 处理是否缓存 */
useActivated(
  watchParams,
  { watchParams },
  [
    { key: 'deviceLongitude', path: 'watchParams.deviceLongitude' },
    { key: 'deviceLatitude', path: 'watchParams.deviceLatitude' },
    { key: 'userLatitude', path: 'watchParams.userLatitude' },
    { key: 'userLongitude', path: 'watchParams.userLongitude' }
  ],
  handleActivated,
  []
)
</script>

<template>
  <div class="xy-map-container">
    <div ref="mapContainer" id="map-container">
      <search-place :auto="auto" :map="map!" :place-search="placeSearch" />
      <measure-tools :ruler="ruler" class="measure-tools-menu" />
      <div class="location-info">
        <div class="location-info__item">
          <img :src="phoneIconImg" alt="" w-15 h-15 mr-5 />
          <div border border-solid class="border-[#e4e7ed]" p-5 max-w-220 text-10>
            <span leading-snug>操作位置:{{ userAddress }}</span>
          </div>
        </div>
        <div class="location-info__item">
          <img :src="bikeIconImg" alt="" w-15 h-15 mr-5 />
          <div border border-solid class="border-[#e4e7ed]" p-5 max-w-220 text-10>
            <span leading-snug>车辆位置:{{ bikeAddress }}</span>
          </div>
        </div>
        <div class="location-info__footer" text-8>
          <span mr-30>操作时间:{{ watchParams.createdTime }}</span>
          <span>操作距离:{{ distance.toFixed(2) }}米</span>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
:deep(.amap-marker-label) {
  border: none;
  font-size: 12px;
  line-height: 14px;
  color: #333333;
  background: #ffffff;
  border-radius: 5px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  white-space: nowrap;
}
.location-info {
  position: absolute;
  z-index: 999;
  top: 80px;
  left: 20px;
  padding: 10px;
  border-radius: 4px 4px 4px 4px;
  background: #ffffff;
  display: flex;
  flex-direction: column;
  &__item {
    display: flex;
    align-items: center;
    margin-bottom: 15px;
  }
  &__footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
  }
}
.measure-tools-menu {
  position: absolute;
  top: 20px;
  right: 70px;
  z-index: 200;
  background-color: #fff;
  padding: 10px 10px;
  box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.1);
  border-radius: 5px 5px 5px 5px;
}
</style>
